#pragma once

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// void Daemon()
// {
//     // 1. 忽略信号，SIGPIPE，SIGCHLD
//     signal(SIGPIPE, SIG_IGN);
//     signal(SIGCHLD, SIG_IGN);
//     // 2. 不要让自己成为组长
//     if (fork() > 0)
//         exit(0);
//     // 3. 调用setsid
//     setsid();
//     // 4. 标准输入，标准输出，标准错误的重定向,守护进程不能直接向显示器打印消息
//     int devnull = open("/dev/null", O_RDONLY | O_WRONLY);
//     if(devnull > 0)
//     {
//         dup2(0, devnull);
//         dup2(1, devnull);
//         dup2(2, devnull);
//         close(devnull);
//     }
// }
void Daemon()
{
    pid_t pid;

    // 创建子进程
    pid = fork();

    if (pid < 0)
    {
        std::cerr << "fork failed" << std::endl;
        exit(EXIT_FAILURE);
    }

    // 如果有父进程，那么让它先退出
    if (pid > 0)
    {
        exit(EXIT_SUCCESS);
    }

    // 在子进程中创建新会话
    if (setsid() < 0)
    {
        exit(EXIT_FAILURE);
    }
    // 捕获、忽略和处理信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    // 创建孙子进程
    pid = fork();

    if (pid < 0)
    {
        std::cerr << "fork failed" << std::endl;
        exit(EXIT_FAILURE);
    }

    // 父进程（即子进程）退出
    if (pid > 0)
    {
        exit(EXIT_SUCCESS);
    }

    // // 改变文件模式掩码
    // umask(0);

    // // 改变工作目录
    // chdir("/");

    int devnull = open("/dev/null", O_RDONLY | O_WRONLY);
    if(devnull > 0)
    {
        dup2(0, devnull);
        dup2(1, devnull);
        dup2(2, devnull);
        close(devnull);
    }
}